﻿using System;
using System.Collections.Generic;

namespace Centido.Management.ConsoleManager
{
    /// <summary>
    ///   An abstract set of console commands.
    /// </summary>
    internal abstract class CommandSet
    {
        /// <summary>
        ///   The set of console commands.
        /// </summary>
        private readonly Dictionary<string, Command> _commands = new Dictionary<string, Command>();


        /// <summary>
        ///   Creates a new instance of the <see cref="Centido.Management.ConsoleManager.CommandSet"/> class.
        /// </summary>
        protected CommandSet()
        {
            PopulateCommandSet();
        }


        /// <summary>
        ///   Gets the list of commands of the command set.
        /// </summary>
        public IEnumerable<Command> Commands
        {
            get { return _commands.Values; }
        }


        /// <summary>
        ///   Retrives a console command with the specified name from the command set.
        /// </summary>
        /// <param name="commandName">The command name.</param>
        /// <exception cref="ArgumentNullException">Thrown when the value of <paramref name="commandName"/> is null.</exception>
        /// <returns>Returns a console command with the specified name from the set if there is one;
        /// otherwise, returns null.</returns>
        public Command GetCommandByName(string commandName)
        {
            if (commandName == null)
                throw new ArgumentNullException("commandName");

            return _commands.ContainsKey(commandName) ? _commands[commandName] : null;
        }


        /// <summary>
        ///   Registeres the specified console command in the command set.
        /// </summary>
        /// <param name="command">The console command to be registered.</param>
        /// <exception cref="ArgumentNullException">Thrown when the value of <paramref name="command"/> is null.</exception>
        protected void RegisterCommand(Command command)
        {
            if (command == null) 
                throw new ArgumentNullException("command");

            if (!_commands.ContainsKey(command.Name))
                _commands.Add(command.Name, command);
        }


        /// <summary>
        ///   Unregisters the specified console command from the command set.
        /// </summary>
        /// <param name="command">The console command to be unregistered.</param>
        /// <exception cref="ArgumentNullException">Thrown when the value of <paramref name="command"/> is null.</exception>
        protected void UnregisterCommand(Command command)
        {
            if (command == null)
                throw new ArgumentNullException("command");

            if (_commands.ContainsKey(command.Name))
                _commands.Remove(command.Name);
        }


        /// <summary>
        ///   Populates the command set.
        /// </summary>
        private void PopulateCommandSet()
        {
            RegisterCommand(new HelpCommand());
            RegisterCommand(new ExitCommand());
        }
    }
}
